#include "util/logger.h"
#include "util/timer.h"
#include <ctime>
#include <thread>

NS_UTIL_BEGIN
LoggerTargetBase::LoggerTargetBase()
{
}

LoggerTargetBase::~LoggerTargetBase()
{
}

// LoggerConsole
void LoggerConsole::Log(int MSG_TYPE, const std::string& msg)
{
	while(!msg_mutex.try_lock()){}
	std::string logmsg;
	std::string retstr;
	switch(MSG_TYPE)
	{
	case MSG:	logmsg = "MSG: "; retstr = "\n"; break;
	case WRN:	logmsg = "WRN: "; retstr = "\n"; break;
	case ERR:	logmsg = "ERR: "; retstr = "\n"; break;
	case DBG:	logmsg = "DBG: "; retstr = "\n"; break;
	case TMP:	logmsg = "\rTMP: "; break; retstr = "        ";	// No return
	case PRN:	break;
	default:	break;
	}
	logmsg += msg;
	logmsg += retstr;
	msg_buffer.push_back(logmsg);
	msg_mutex.unlock();
}

void LoggerConsole::refresh()
{
	if(msg_buffer.empty())return;
	while(!msg_mutex.try_lock()){}
	// Swap to a temp buffer
	std::vector<std::string> tmp_buffer;
	tmp_buffer.swap(msg_buffer);
	msg_mutex.unlock();
	std::string TMP_STR;
	Timer timer;
	for(auto iter=tmp_buffer.begin();iter!=tmp_buffer.end();++iter)
	{
		if(iter->substr(0,5)=="\rTMP:")
		{
			TMP_STR = (*iter);
			if(TMP_STR.empty())timer.tic();
			else
			{
				double t = timer.toc();
				if(t>0.3)
				{
					std::cout<<(*iter);
					timer.tic();
				}
			}
		}else
		{
			if(TMP_STR.empty())
			{
				std::cout<<(*iter);
			}else
			{

				std::cout<<TMP_STR<<std::endl;
				TMP_STR.clear();
				std::cout<<(*iter);
			}			
		}
	}	
}

LoggerConsole::~LoggerConsole()
{
}


// Logger
Logger::Logger(){}
Logger::~Logger(){}


void Logger::SetData(LoggerTargetBase* logtarget)
{
	this->target = logtarget;
}

void Logger::LogMessage(const std::string& msg)
{
	target->Log(MSG, msg);
}

void Logger::LogDebug(const std::string& msg)
{
	target->Log(DBG, msg);
}

void Logger::LogWarning(const std::string& msg)
{
	target->Log(WRN, msg);
}

void Logger::LogError(const std::string& msg)
{
	target->Log(ERR, msg);
}

void Logger::LogPrint(const std::string& msg)
{
	target->Log(PRN, msg);
}

void Logger::LogPrintLine(const std::string& msg)
{
	std::string msg_with_CR = msg + "\n";
	target->Log(PRN, msg_with_CR);
}

void Logger::LogPrintTmp(const std::string& msg)
{
	target->Log(TMP, msg);
}

void Logger::refresh()
{
	target->refresh();
}


NS_UTIL_END